package com.fate.system.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fate.framework.dto.TreeNodeDTO;
import com.fate.framework.exception.KKException;
import com.fate.framework.utils.CommonUtil;
import com.fate.framework.utils.SystemUtil;
import com.fate.system.dto.org.OrgAddDTO;
import com.fate.system.dto.org.OrgPageDTO;
import com.fate.system.dto.org.OrgUpdateDTO;
import com.fate.system.dto.org.OrgUserPageDTO;
import com.fate.system.dto.user.UserPageDTO;
import com.fate.system.entity.Org;
import com.fate.system.entity.User;
import com.fate.system.mapper.OrgMapper;
import com.fate.system.service.IDictService;
import com.fate.system.service.IOrgService;
import com.fate.system.service.IUserOrgService;
import com.fate.system.service.IUserService;
import com.fate.system.vo.org.OrgTreeVO;
import com.fate.system.vo.user.UserListVO;
import jakarta.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.springframework.stereotype.Service;

/**
 * @author 47349
 * @description 针对表【sys_org(组织机构表)】的数据库操作Service实现
 * @createDate 2024-08-09 01:53:43
 */
@Service
public class OrgServiceImpl extends ServiceImpl<OrgMapper, Org> implements IOrgService {

  @Resource private IUserOrgService userOrgService;
  @Resource private IDictService dictService;
  @Resource private IUserService userService;

  public Page<Org> getPageList(OrgPageDTO pageDTO) {
    Page<Org> page = SystemUtil.buildPageFromDTO(pageDTO, Org.class);
    return this.lambdaQuery().orderByDesc(Org::getGmtCreate).page(page);
  }

  @Override
  public List<OrgTreeVO> treeList() {
    List<Org> orgList = this.list();
    if (CommonUtil.isNullOrEmpty(orgList)) {
      return new ArrayList<>();
    }

    Map<String, Org> orgId2OrgMap =
        orgList.stream().collect(Collectors.toMap(Org::getId, Function.identity()));

    List<OrgTreeVO> orgTreeDTOList = SystemUtil.buildResource(orgList, OrgTreeVO.class);
    orgTreeDTOList.forEach(
        i -> i.setOrderNumber(orgId2OrgMap.get((String) i.getId()).getOrderNumber()));

    return TreeNodeDTO.buildTreeFromFlatList(orgTreeDTOList, true);
  }

  @Override
  public void removeOrg(String id) {
    Org org = this.getById(id);
    if (CommonUtil.isNullOrEmpty(org)) {
      throw new KKException("组织机构不存在");
    }

    List<String> userIdList = userOrgService.getUserIdListByOrgIds(List.of(id));

    if (CommonUtil.notNullOrEmpty(userIdList)) {
      throw new KKException("组织机构下存在用户");
    }

    String path = org.getOrgPath();
    List<Org> orgList =
        this.lambdaQuery().select(Org::getId).likeRight(Org::getOrgFullPath, path).list();
    if (CommonUtil.notNullOrEmpty(orgList) && orgList.size() > 1) {
      throw new KKException("组织机构下存在子组织机构");
    }

    this.removeById(id);
  }

  @Override
  public void addOrg(OrgAddDTO orgAddDTO) {
    String path = orgAddDTO.getOrgPath();
    if (!path.startsWith("#")) {
      throw new KKException("组织机构路径必须以#开头");
    }

    String pid = orgAddDTO.getPid();
    String fullPathPrefix = "";
    if (CommonUtil.notNullOrEmpty(pid)) {
      Org parentOrg = this.getById(pid);
      fullPathPrefix = parentOrg.getOrgFullPath();
    }

    Org org = SystemUtil.buildResource(orgAddDTO, Org.class);
    org.setOrgFullPath(fullPathPrefix + org.getOrgPath());
    this.save(org);
  }

  @Override
  public void updateOrg(OrgUpdateDTO updateDTO) {
    Org org = SystemUtil.buildResource(updateDTO, Org.class);
    this.updateById(org);
  }

  @Override
  public Page<UserListVO> getOrgUserList(OrgUserPageDTO orgUserPageDTO) {
    Org org = this.getById(orgUserPageDTO.getOrgId());
    String path = org.getOrgPath();
    List<Org> orgList =
        this.lambdaQuery()
            .select(Org::getId)
            .eq(Org::getOrgPath, path)
            .or()
            .likeRight(Org::getOrgFullPath, path)
            .list();
    if (CommonUtil.isNullOrEmpty(orgList)) {
      return new Page<>();
    }
    List<String> orgIdList = orgList.stream().map(Org::getId).toList();
    List<String> userIds = userOrgService.getUserIdListByOrgIds(orgIdList);
    if (CommonUtil.isNullOrEmpty(userIds)) {
      return new Page<>();
    }

    Map<String, List<String>> userId2OrgNameMap = userOrgService.getUserId2OrgNameMap(userIds);

    UserPageDTO userPageDTO = SystemUtil.buildResource(orgUserPageDTO, UserPageDTO.class);
    userPageDTO.setUserIds(userIds);
    Page<User> pageUserList = userService.getPageList(userPageDTO);

    Page<UserListVO> buildResource = SystemUtil.buildResource(pageUserList, UserListVO.class);

    List<UserListVO> records = buildResource.getRecords();

    records.forEach(
        i -> {
          List<String> orgNames = userId2OrgNameMap.get(i.getId());
          if (CommonUtil.notNullOrEmpty(orgNames)) {
            i.setBelongOrgNameList(orgNames);
          }
        });

    dictService.transfer(buildResource);

    return buildResource;
  }
}
